<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    var person = {
            name:"Lily",
            0:123,
            "first name":"liu",
        }
    // person.0   Uncaught SyntaxError: Unexpected number
    person['0']
    // 通过点号(.)运算符
    //     点号要求后面的属性名是合法的标识符，对于不合法的不可以使用
    // 通过中括号([])运算符
    //     中括号要求的则是一个字符串即可，不必是合法的标识符

    // 通过[] 更方便的实现 但是占的内存比.多 看情况使用
    for(var i=0;i<3;i++){
        person["name" + i] = i;
    }
    person
    
    // && 左侧true 返回右操作数
    // || 左侧true 返回左操作数

    console.log(true&&2>3) //false
    console.log(2&&4) //4
    // console.log({x:2}&&{name:jack})
    // VM723:1 Uncaught ReferenceError: jack is not defined
    //     at <anonymous>:1:26
    console.log({x:2}&&{name:"jack"}) //{name:"jack"}

    console.log(""&&{2:2}) //""
    console.log(""&&{x:2}) //""
    console.log(""||{2:2}) //{2:2}

    //操作数非布尔类型，&&短路原则
    console.log(2 && 4);
    console.log(0 && 4);
    console.log({ x: 2 } && { name: "Jack" });
    console.log(null && "hello");
    console.log({} && "world");

    //操作数非布尔类型，||短路原则
    console.log(2 || 4); //2
    console.log(0 || 4); //4
    console.log({ x: 2 } || { name: "Jack" }); //{x: 2}
    console.log(null || "hello"); //hello
    console.log({} || "world"); // {}

    //思考 所有对象转换为布尔类型 都为 true
    console.log(new Boolean(false) && 234); //234 true
    console.log(new Boolean(false) || 234); //Boolean {false}
    new Boolean(false)
    typeof(new Boolean(false)); //object

    // 遵循短路特性，使用 || 来设置函数参数的默认值
    /***使用 || 来设置函数参数的默认值***/

    //定义一个计算圆面积的函数area_of_circle()，它有两个参数：
    //r: 表示圆的半径；
    //pi: 表示π的值，如果不传，则默认3.14

    function area_of_circle(r, pi) {
    var temp = 3.14;
        if (arguments.length > 1) {
            temp = pi;
        }
        return temp * r * r;
    }

    // 简化代码
    function area_of_circle(r, pi) {
        //补全代码
        return r*r*(pi||3.14);  //设置默认参数
    }

    /***使用 && 提升程序健壮性***/
    //定时5秒完成任务，确保传递了callback并且callback是函数才执行callback()
    // function animate(callback) {
    //     setTimeout(function() {
    //         //do something
    //         var a=1;
    //         //....
    //         // callback && callback();
    //         callback && typeof callback === 'function' && callback();
    //     }, 5000);
    // }

    // 不传参，传参不正确都会崩溃报错;
    function animate(callback) {
        setTimeout(function() {
            //do something
            var a=1;
            callback();
        }, 5000);
    }
    animate();  //崩溃 Uncaught TypeError: callback is not a function
    animate(2); //崩溃
    var foo = function(){console.log("xxx");};
    animate(foo);

    // 不传参没事，输出undefined;传的不是函数会崩溃;传入函数正常
    function animate(callback) {
        setTimeout(function() {
            //do something
            var a=1;
            callback && callback();
        }, 5000);
    }
    animate(); 
    animate(2); //崩溃
    var foo = function(){console.log("xxx");};
    animate(foo);

    // 不论传什么都不会报错，只是会影响是否执行回调callback函数；
    function animate(callback) {
        setTimeout(function() {
            //do something
            var a=1;
            //callback();
            // callback && callback();
            callback && typeof callback === 'function' && callback();
        }, 5000);
    }
    animate();
    animate(2);
    var foo = function(){console.log("xxx");};
    animate(foo);

    // 简化 if 语句
    /***使用 &&和|| 可用来实现条件语句***/
    var score = 76;
    if (score > 90) {
        console.log("优");
    } else if (score > 75) {
        console.log("良");
    } else if (score > 60) {
        console.log("及格");
    } else {
        console.log("不及格");
    }

    //通过&&和||的组合实现如上功能，注：小括号优先级最高
    console.log(
        (score > 90 && "优") ||
        (score > 75 && "良") ||
        (score > 60 && "及格") ||
        "不及格"
    );

    //  JavaScript 有两种比较方式：严格比较运算符和宽松比较运算符。
    console.log(null == undefined);//true 
    console.log(null === undefined);//false

    console.log([2] == 2);//true  引用数据类型和基本数据类型
    console.log([2] === 2);//f

    console.log({} == {});//false  引用数据类型和引用数据类型
    console.log({} === {});//f

    var a = "1";
    var b = true;
    var c = 1;
    console.log(a == b == c); //t
    console.log(a === b == c); //f
    console.log(a == b === c); //f
    console.log(a === b === c); //f

    var a = "1";
    var b = true;
    var c = 0;
    console.log(a == b == c); //f
    console.log(a === b == c); //t
    console.log(a == b === c);//f
    console.log(a === b === c);//f

    //赋值
    function fun() {
        var a = b = 5;
        console.log(a, typeof a); //5 'number'
        console.log(b, typeof b); //5 'number'
    }
    fun();
    
    var a = { n: 1 };
    var b = a;
    // a、b指向了同一个地址 内容是{n ： 1}
    a.x = a = { n: 2 };
    // 先b.x = a.x = 占位 右侧的结果 {n : 2}(异步的 将未来的结果赋过去)
    // 再a = { n: 2 } 即a与原来的断开了，a指向了新的对象{ n: 2 }
    console.log(a.x);
    // undefined;
    console.log(b);
    // {n:1 x:{n:2}}

    // //上述代码等效于
    // var a = { n: 1 };
    // var b = a;
    // a.x = ;
    // a = {n:2};
    // (a)b.x = {n:2}
    // console.log(a.x);
    // console.log(b);

    //练习2的变形
    var a = { n: 1 };
    a.x = a = { n: 2 };
    console.log(a.x);
    // undefined 
    // 过段时间垃圾处理机制会把原来的a指的空间清除掉

    // 如何避免=与==混淆（表达式反写） 会报错 防止将 == 写成=
    // PPT

    // 立即执行表达式
    //立即执行表达式 常见形式
    (function max( x,y){
        console.log("the max is",x>y?x:y);
    }(2,3));

    (function (x,y){ //可以没有函数名
        console.log("the min is",x<y?x:y);
    })(2,3);

    //注意：IIFE是表达式，要注意使用分号结尾，否则可能出现错误
    // 其他形式的IIFE 与运算符结合的写法
    var i = function(){
        return 10;
    }(); //i为10
    var i = function(){
        return 10;
    };
    console.log(i) //i是函数

    true && function(a,b){
        return a>b?a:b;
    }(5,9);

    !function(x,y){
        return x==y?true:false; // === 返回什么
    }("5",5);

    //思考 !function(){return 2; }(); 与 !function(){return 0; }();
    // false true

    function Student(name, age) {
        this.name = name;
        this.age = age;
    }
    var stu1 = Student("Lily", 18);
    var stu2 = new Student("Lucy", 20);
    console.log(typeof stu1); //undefined

    // switch  case default break
    // for in 对象
    // for of 数组


</script>
</html>